﻿using System;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Linq.Expressions;
using Isuka.Reflection;

namespace Isuka.Auxiliaries
{
    /// <summary>
    /// よくある通知オブジェクト
    /// </summary>
    public class NotificationObject
        : INotifyPropertyChanged
    {
        /// <summary>
        /// プロパティの値が変更されたことを通知する
        /// </summary>
        /// <param name="propertyName">値が変更されたプロパティの名称</param>
        protected virtual void RaisePropertyChanged(string propertyName)
        {
            Contract.Requires<ArgumentNullException>(propertyName != null, "propertyName");
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));                
            }
        }

        /// <summary>
        /// 複数プロパティの値が同時に変更されたことを通知する
        /// </summary>
        /// <param name="propertyNames">値が変更されたプロパティの名称の一覧</param>
        protected void RaisePropertyChanged(params string[] propertyNames)
        {
            Contract.Requires<ArgumentNullException>(propertyNames != null, "propertyNames");
            Contract.Requires(Contract.ForAll(propertyNames, x => x != null));

            Array.ForEach(propertyNames, RaisePropertyChanged);
        }

        /// <summary>
        /// プロパティの値が変更されたことを通知する
        /// </summary>
        /// <param name="propertyExpression">値が変更されたプロパティを示すラムダ式</param>
        protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
        {
            Contract.Requires<ArgumentNullException>(propertyExpression != null, "propertyExpression");

            var memberInfo = MemberHelper.GetMemberInfo(propertyExpression);
            if (memberInfo != null)
            {
                RaisePropertyChanged(memberInfo.Name);
            }
        }

        #region INotifyPropertyChanged メンバー

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}
